
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>动态代理与Mapper接口 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>动态代理与Mapper接口 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在MyBatis中，动态代理技术的核心目标是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">动态代理的核心目标是将Mapper接口的方法调用转化为对 `MappedStatement` 的执行，并通过SQL语句和参数进行动态绑定，从而将接口与实际的数据库操作关联起来。</div>
          </div>
          <div class="card-source">来源: 1. Mapper接口与动态代理的核心关系</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">MyBatis的 `SqlSession` 是如何为Mapper接口创建代理对象的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过调用 `getMapper(Class<T> type)` 方法。该方法的默认实现 `DefaultSqlSession` 使用 `Proxy.newProxyInstance()` 来创建一个Mapper接口的动态代理对象，并将方法调用委托给一个 `MapperProxy` 实例来处理。</div>
          </div>
          <div class="card-source">来源: 2. SqlSession与Mapper接口的映射</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">角色</div>
          <div class="card-question">`MapperProxy` 类在MyBatis的动态代理机制中扮演什么角色？它实现了哪个核心Java接口？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">角色</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`MapperProxy` 是MyBatis中的动态代理实现，它负责拦截对Mapper接口方法的调用，并将其转化为SQL执行操作。它实现了Java的 `InvocationHandler` 接口，通过重写 `invoke` 方法来处理方法调用。</div>
          </div>
          <div class="card-source">来源: 3. MapperProxy的工作原理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">当调用一个Mapper接口的方法时，`MapperProxy` 是如何处理这个调用的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当Mapper接口的方法被调用时，`MapperProxy` 的 `invoke` 方法会被触发。该方法会创建一个 `MapperMethod` 对象，并调用其 `execute` 方法，将 `SqlSession`、调用的方法和参数传递进去，从而执行具体的SQL操作。</div>
          </div>
          <div class="card-source">来源: 3. MapperProxy的工作原理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">角色</div>
          <div class="card-question">MyBatis中的 `MapperMethod` 类的主要作用是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">角色</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`MapperMethod` 是一个核心类，它的主要作用是负责将Mapper接口的方法与具体的SQL语句进行绑定，并通过 `SqlSession` 来执行对应的SQL操作。</div>
          </div>
          <div class="card-source">来源: 4. MapperMethod的作用与执行流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">概念</div>
          <div class="card-question">`MappedStatement` 对象封装了哪些核心信息？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">概念</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`MappedStatement` 封装了一个SQL语句及其所有相关的执行信息，包括SQL语句本身、SQL命令的类型（如查询、插入、更新等），以及通过 `BoundSql` 与具体参数的绑定关系。</div>
          </div>
          <div class="card-source">来源: 5. MappedStatement的构建与SQL绑定</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">请简述 `MapperMethod` 的 `execute` 方法是如何执行SQL的。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`execute` 方法首先根据被调用的方法名从配置中获取对应的 `MappedStatement` 对象。然后，它使用 `MappedStatement` 和传入的参数构建一个 `BoundSql` 对象。最后，它调用 `SqlSession` 的方法（如 `selectOne`）来执行 `BoundSql` 中的SQL语句并返回结果。</div>
          </div>
          <div class="card-source">来源: 4. MapperMethod的作用与执行流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">关系</div>
          <div class="card-question">`MappedStatement` 和 `BoundSql` 之间是什么关系？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">关系</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`MappedStatement` 包含了SQL语句的模板和执行方式。`BoundSql` 是 `MappedStatement` 与具体调用参数绑定的产物，它包含了最终可以被数据库执行的、带有参数值的SQL语句。</div>
          </div>
          <div class="card-source">来源: 4. MapperMethod的作用与执行流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">请概括MyBatis从调用 `SqlSession.getMapper()` 到最终执行SQL的完整流程。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. **获取代理对象**: 调用 `SqlSession.getMapper()` 方法，MyBatis使用动态代理创建一个与 `MapperProxy` 关联的Mapper接口代理对象。<br>2. **方法调用**: 调用代理对象的方法时，`MapperProxy` 的 `invoke` 方法被触发，该方法进而调用 `MapperMethod.execute()`。<br>3. **执行SQL**: `MapperMethod` 查找对应的 `MappedStatement`，将参数绑定生成 `BoundSql`，最后通过 `SqlSession` 执行SQL并返回结果。</div>
          </div>
          <div class="card-source">来源: 6. 动态代理与SQL映射的执行流程</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
